#include "tracelog.h"                   // Required for: LogType enum
#include <stdio.h>                      // Required for: vprintf()
#include <stdlib.h>                     // Required for: exit(), EXIT_FAILURE
#include <stdarg.h>                     // Required for: va_list
#include <string.h>                     // Required for: strcpy(), strcat()

#define MAX_TRACELOG_MSG_LENGTH     128     // Max length of one trace-log message

u8 LogTypes = LOG_INFO | LOG_WARNING | LOG_ERROR | LOG_FATAL | LOG_CYCLE;
u8 ExitTypes = LOG_FATAL;

void SetLogLevel(u8 type) { LogTypes = type; }
void SetExitLevel(u8 type) { ExitTypes = type; }
void SetBitLogLevel(u8 type) { LogTypes |= type; }
void ClearBitLogLevel(u8 type) { LogTypes &=~ type; }
void SetBitExitLevel(u8 type) { ExitTypes |= type; }
void ClearBitExitLevel(u8 type) { ExitTypes &=~ type; }

void TraceLog(u8 type, const char *text, ...)
{
    // Message has level below current threshold, don't emit
    if (!(type & LogTypes)) return;
    va_list args;
    va_start(args, text);
    char buffer[MAX_TRACELOG_MSG_LENGTH] = { 0 };
    switch (type) {
        case LOG_TRACE: strcpy(buffer, "TRACE: "); break;
        case LOG_DEBUG: strcpy(buffer, "DEBUG: "); break;
        case LOG_INFO: strcpy(buffer, "INFO: "); break;
        case LOG_WARNING: strcpy(buffer, "WARNING: "); break;
        case LOG_ERROR: strcpy(buffer, "ERROR: "); break;
        case LOG_FATAL: strcpy(buffer, "FATAL: "); break;
        default: break;
    }
    strcat(buffer, text);
    if (type == LOG_CYCLE) strcat(buffer, "\r");
    else                      strcat(buffer, "\n");
    vprintf(buffer, args);
    va_end(args);
    if (type & ExitTypes) exit(EXIT_FAILURE);
}
